/*
 * Android Runner is a multiplayer GPS game fully written by Xurxo Mendez Perez
 * 
 * Copyright (C) 2009 Xurxo Mendez Perez
 *   
 * This file is part of Android Runner.
 * 
 * Android Runner is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Android Runner is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Android Runner.  If not, see <http://www.gnu.org/licenses/>.
 */

package es.sonxurxo.gpsgame.client.model.util.xml;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.http.HttpEntity;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.google.android.maps.GeoPoint;

import es.sonxurxo.gpsgame.client.model.service.to.FinishedGame;
import es.sonxurxo.gpsgame.client.model.service.to.Game;
import es.sonxurxo.gpsgame.client.model.service.to.GameCTO;
import es.sonxurxo.gpsgame.client.model.service.to.Item;
import es.sonxurxo.gpsgame.client.model.service.to.Message;
import es.sonxurxo.gpsgame.client.model.service.to.Player;
import es.sonxurxo.gpsgame.client.model.service.to.PublicPlayerProfileTO;
import es.sonxurxo.gpsgame.client.model.service.to.Question;
import es.sonxurxo.gpsgame.client.model.service.to.response.AnswerQuestionResponseTO;
import es.sonxurxo.gpsgame.client.model.service.to.response.GenericGameResponseTO;
import es.sonxurxo.gpsgame.client.model.service.to.response.GetItemResponseTO;
import es.sonxurxo.gpsgame.client.model.service.to.response.InGamePlayerInfoTO;
import es.sonxurxo.gpsgame.client.model.service.to.response.StartOrContinueGameResponseTO;
import es.sonxurxo.gpsgame.client.util.DateOperations;
import es.sonxurxo.gpsgame.client.util.exception.ServerException;

/**
 * 
 * @author "Xurxo Mendez Perez"
 *
 */
public class XMLToBussinessConversor {

	private static Document parseHttpEntity(HttpEntity entity) throws Exception {
		InputStream in = null;
		try {
			in = entity.getContent();
		} catch (Exception e) {
			throw e;
		}
		
		Document document = null;
		try {
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			document = db.parse(in);
		} catch (IOException ioe) {
			throw ioe;
		} catch (ParserConfigurationException pce) {
			throw new Exception(pce);
		} catch (SAXException se) {
			throw new Exception(se);
		}
		return document;
	}
	
	public static Player toPlayer(HttpEntity entity) throws Exception{

		Player player = new Player();
		Document playerDocument = parseHttpEntity(entity);
		
		if (playerDocument.getElementsByTagName("player").getLength() == 1) {
		
			Element loginElement = (Element)playerDocument.getElementsByTagName(
					"login").item(0);
			String login = loginElement.getChildNodes().item(0).getNodeValue();
			player.setLogin(login.replace("+", " "));

			Element showPersonalInfoElement = (Element)playerDocument.getElementsByTagName(
			"showPersonalInfo").item(0);
			boolean showPersonalInfo = Boolean.parseBoolean(
					showPersonalInfoElement.getChildNodes().item(0).getNodeValue());
			Element emailElement = (Element)playerDocument.getElementsByTagName(
					"email").item(0);
			String email = emailElement.getChildNodes().
			item(0).getNodeValue().replace("+", " ");
			Element phoneElement = (Element)playerDocument.getElementsByTagName(
			"phone").item(0);
			String phone = phoneElement.getChildNodes().item(0).getNodeValue().replace("+", " ");
			Element nameElement = (Element)playerDocument.getElementsByTagName(
			"name").item(0);
			String name = nameElement.getChildNodes().item(0).getNodeValue().replace("+", " ");
			Element surnameElement = (Element)playerDocument.getElementsByTagName(
			"surname").item(0);
			String surname = surnameElement.getChildNodes().item(0).getNodeValue().replace("+", " ");
			
			Element countryElement = (Element)playerDocument.getElementsByTagName(
			"country").item(0);
			String country = countryElement.getChildNodes().item(0).getNodeValue();
			Element imageIdElement = (Element)playerDocument.getElementsByTagName(
			"imageId").item(0);
			String imageId = imageIdElement.getChildNodes().item(0).getNodeValue();
			Element totalPointsElement = (Element)playerDocument.getElementsByTagName(
			"totalPoints").item(0);
			String totalPoints = totalPointsElement.getChildNodes().item(0).getNodeValue();
			Element maxPointsElement = (Element)playerDocument.getElementsByTagName(
					"maxPoints").item(0);
			String maxPoints = maxPointsElement.getChildNodes().item(0).getNodeValue();
			Element bestRankElement = (Element)playerDocument.getElementsByTagName(
					"bestRank").item(0);
			String bestRank = bestRankElement.getChildNodes().item(0).getNodeValue();

			player.setName(name);
			player.setShowPersonalInfo(showPersonalInfo);
			player.setEmail(email);
			player.setPhone(phone);
			player.setSurname(surname);			
			player.setCountry(country.replace("+", " "));
			player.setImageId(Integer.parseInt(imageId));
			player.setTotalPoints(Integer.parseInt(totalPoints));
			player.setMaxPoints(Integer.parseInt(maxPoints));
			player.setBestRank(Integer.parseInt(bestRank));
			
			if (playerDocument.getElementsByTagName("gameId").getLength() == 1) {
				Element gameIdElement = (Element)playerDocument.getElementsByTagName(
					"gameId").item(0);
				long gameId = Long.parseLong(
						gameIdElement.getChildNodes().item(0).getNodeValue());
				player.setGameId(gameId);
			}
			
			return player;
		}
		else {
			Element codeElement = (Element)playerDocument.getElementsByTagName(
					"code").item(0);
			int code = Integer.parseInt(codeElement.getChildNodes().item(0).
					getNodeValue());
			Element messageElement = (Element)playerDocument.getElementsByTagName(
					"message").item(0);
			String message = messageElement.getChildNodes().item(0).getNodeValue();
			
			throw new ServerException(code, message);
		}
	}

	public static PublicPlayerProfileTO toPublicPlayer(HttpEntity entity) throws Exception{

		PublicPlayerProfileTO publicPlayerProfileTO = new PublicPlayerProfileTO();
		Document playerDocument = parseHttpEntity(entity);
		
		if (playerDocument.getElementsByTagName("player").getLength() == 1) {
		
			Element loginElement = (Element)playerDocument.getElementsByTagName(
					"login").item(0);
			String login = loginElement.getChildNodes().item(0).getNodeValue();
			publicPlayerProfileTO.setLogin(login.replace("+", " "));
			boolean showPersonalInfo = false;
			if (playerDocument.getElementsByTagName("email").getLength() == 1) {
				showPersonalInfo = true;
				Element emailElement = (Element)playerDocument.getElementsByTagName(
					"email").item(0);
				String email = emailElement.getChildNodes().
					item(0).getNodeValue().replace("+", " ");
				Element phoneElement = (Element)playerDocument.getElementsByTagName(
					"phone").item(0);
				String phone = phoneElement.getChildNodes().item(0).getNodeValue().replace("+", " ");
				Element nameElement = (Element)playerDocument.getElementsByTagName(
					"name").item(0);
				String name = nameElement.getChildNodes().item(0).getNodeValue().replace("+", " ");
				Element surnameElement = (Element)playerDocument.getElementsByTagName(
					"surname").item(0);
				String surname = surnameElement.getChildNodes().item(0).getNodeValue().replace("+", " ");
				
				publicPlayerProfileTO.setName(name.replace("+", " "));
				publicPlayerProfileTO.setEmail(email.replace("+", " "));
				publicPlayerProfileTO.setPhone(phone.replace("+", " "));
				publicPlayerProfileTO.setSurname(surname.replace("+", " "));
			}
			publicPlayerProfileTO.setShowPersonalInfo(showPersonalInfo);			
			Element countryElement = (Element)playerDocument.getElementsByTagName(
			"country").item(0);
			String country = countryElement.getChildNodes().item(0).getNodeValue();
			Element imageIdElement = (Element)playerDocument.getElementsByTagName(
			"imageId").item(0);
			String imageId = imageIdElement.getChildNodes().item(0).getNodeValue();
			Element totalPointsElement = (Element)playerDocument.getElementsByTagName(
			"totalPoints").item(0);
			String totalPoints = totalPointsElement.getChildNodes().item(0).getNodeValue();
			Element maxPointsElement = (Element)playerDocument.getElementsByTagName(
					"maxPoints").item(0);
			String maxPoints = maxPointsElement.getChildNodes().item(0).getNodeValue();
			Element bestRankElement = (Element)playerDocument.getElementsByTagName(
					"bestRank").item(0);
			String bestRank = bestRankElement.getChildNodes().item(0).getNodeValue();
			
			publicPlayerProfileTO.setCountry(country.replace("+", " "));
			publicPlayerProfileTO.setImageId(Integer.parseInt(imageId));
			publicPlayerProfileTO.setTotalPoints(Integer.parseInt(totalPoints));
			publicPlayerProfileTO.setMaxPoints(Integer.parseInt(maxPoints));
			publicPlayerProfileTO.setBestRank(Integer.parseInt(bestRank));
			
			return publicPlayerProfileTO;
		}
		else {
			Element codeElement = (Element)playerDocument.getElementsByTagName(
					"code").item(0);
			int code = Integer.parseInt(codeElement.getChildNodes().item(0).
					getNodeValue());
			Element messageElement = (Element)playerDocument.getElementsByTagName(
					"message").item(0);
			String message = messageElement.getChildNodes().item(0).getNodeValue();
			
			throw new ServerException(code, message);
		}
	}

	
	public static List<FinishedGame> toFinishedGameList(HttpEntity entity) 
	throws Exception {
		Document fgListDocument = parseHttpEntity(entity);
		List<FinishedGame> fgList = new ArrayList<FinishedGame>();
		
		if (fgListDocument.getElementsByTagName("games").getLength() == 1) {
			NodeList games = fgListDocument.getElementsByTagName("game");
			for (int i=0;i<games.getLength();i++) {
				
				FinishedGame fg = toFinishedGame((Element)games.item(i));
				fgList.add(fg);

			}
		}
		return fgList;
	}
	
	private static FinishedGame toFinishedGame(Element fgElement) {
		FinishedGame fg = new FinishedGame();
		Element gameIdElement = (Element)fgElement.getElementsByTagName("gameId").item(0);
		long gameId = Long.parseLong(gameIdElement.getChildNodes().item(0).getNodeValue());
		
		Element cityElement = (Element)fgElement.getElementsByTagName("city").item(0);
		String city = cityElement.getChildNodes().item(0).getNodeValue();
		
		Element startDateElement = (Element)fgElement.getElementsByTagName("startDate").item(0);
		Calendar startDate = DateOperations.formatString(
				startDateElement.getChildNodes().item(0).getNodeValue());
		
		NodeList rankingLines = fgElement.getElementsByTagName("rankingLine");
		List<String> logins = new ArrayList<String>();
		List<Integer> points = new ArrayList<Integer>();
		List<Integer> itemsCaughted = new ArrayList<Integer>();
		List<Integer> positions = new ArrayList<Integer>();
		for (int i=0;i<rankingLines.getLength();i++) {
			Element loginElement = (Element)((Element)rankingLines.item(i)).
				getElementsByTagName("login").item(0);
			logins.add(loginElement.getChildNodes().item(0).getNodeValue().replace("+", " "));
			
			Element pointsElement = (Element)((Element)rankingLines.item(i)).
				getElementsByTagName("points").item(0);
			points.add(Integer.parseInt(pointsElement.getChildNodes().item(0).
					getNodeValue()));
		
			Element itemsElement = (Element)((Element)rankingLines.item(i)).
				getElementsByTagName("numberOfItems").item(0);
			itemsCaughted.add(Integer.parseInt(itemsElement.getChildNodes().item(0).
					getNodeValue()));
			Element positionElement = (Element)((Element)rankingLines.item(i)).
				getElementsByTagName("position").item(0);
			positions.add(Integer.parseInt(positionElement.getChildNodes().item(0).
					getNodeValue()));
		}
		fg.setGameId(gameId);
		fg.setCity(city.replace("+", " "));
		fg.setStartDate(startDate);
		fg.setLogins(logins);
		fg.setPoints(points);
		fg.setItemsCaughted(itemsCaughted);
		fg.setPositions(positions);
		return fg;
	}
	
	public static Game toGame(HttpEntity entity) throws Exception{
		
		Document gameDocument = parseHttpEntity(entity);
		
		if (gameDocument.getElementsByTagName("game").getLength() == 1) {
		
			return toGame((Element)gameDocument.getElementsByTagName("game").item(0));

		}
		else {
			Element codeElement = (Element)gameDocument.getElementsByTagName(
					"code").item(0);
			int code = Integer.parseInt(codeElement.getChildNodes().item(0).
					getNodeValue());
			Element messageElement = (Element)gameDocument.getElementsByTagName(
					"message").item(0);
			String message = messageElement.getChildNodes().item(0).getNodeValue();
			
			throw new ServerException(code, message);
		}
	}
	
	public static List<String> toCityList(HttpEntity entity) throws Exception {
		
		Document citiesDocument = parseHttpEntity(entity);
		List<String> cityList = new ArrayList<String>();
		
		if (citiesDocument.getElementsByTagName("cities").getLength() == 1) {
			NodeList cities = citiesDocument.getElementsByTagName("city");
			for (int i=0;i<cities.getLength();i++) {
				cityList.add(cities.item(i).getChildNodes().item(0).getNodeValue());
			}
		}
		return cityList;
	}
	
	private static Game toGame(Element gameDocument) throws Exception {
		Game game = new Game();
		
		Element gameIdElement = (Element)gameDocument.getElementsByTagName(
		"gameId").item(0);
		long gameId = Long.parseLong(gameIdElement.getChildNodes().item(0).getNodeValue());
		
		Element startDateElement = (Element)gameDocument.getElementsByTagName(
			"startDate").item(0);
		String startDate = startDateElement.getChildNodes().item(0).getNodeValue();
		
		Element finishDateElement = (Element)gameDocument.getElementsByTagName(
			"finishDate").item(0);
		String finishDate = finishDateElement.getChildNodes().item(0).getNodeValue();
		
		Element cityElement = (Element)gameDocument.getElementsByTagName(
				"city").item(0);
		String city = cityElement.getChildNodes().item(0).getNodeValue();
		
		Element pointsToWinElement = (Element)gameDocument.getElementsByTagName(
		"pointsToWin").item(0);
		int pointsToWin = Integer.parseInt(pointsToWinElement.getChildNodes().item(0).getNodeValue());
		
		Element availablePointsElement = (Element)gameDocument.getElementsByTagName(
		"availablePoints").item(0);
		int availablePoints = Integer.parseInt(availablePointsElement.getChildNodes().item(0).getNodeValue());
		
		Element currentPlayersElement = (Element)gameDocument.getElementsByTagName(
		"currentPlayers").item(0);
		int currentPlayers = Integer.parseInt(currentPlayersElement.getChildNodes().item(0).getNodeValue());
		
		Element maxPlayersElement = (Element)gameDocument.getElementsByTagName(
			"maxPlayers").item(0);
		int maxPlayers = Integer.parseInt(maxPlayersElement.getChildNodes().item(0).getNodeValue());
		
		game.setGameId(gameId);
		game.setStartDate(DateOperations.formatString(startDate));
		game.setFinishDate(DateOperations.formatString(finishDate));
		game.setCity(city.replace("+", " "));
		game.setPointsToWin(pointsToWin);
		game.setAvailablePoints(availablePoints);
		game.setMaxPlayers(maxPlayers);
		game.setCurrentPlayers(currentPlayers);
		return game;
	}
	
	public static GameCTO toGameList(HttpEntity entity) throws Exception{
		
		List<Game> gameList = new ArrayList<Game>();
		Document gamesDocument = parseHttpEntity(entity);

		boolean hasMore = false;
		if (gamesDocument.getElementsByTagName("gameList").getLength() == 1) {
			if (gamesDocument.getElementsByTagName("hasMore").getLength() == 1)
				hasMore = true;
			NodeList games = gamesDocument.getElementsByTagName("game");
			for (int i=0;i<games.getLength();i++) {
				Game game = toGame((Element)games.item(i));
				gameList.add(game);
			}
		}
		else {
			Element codeElement = (Element)gamesDocument.getElementsByTagName(
					"code").item(0);
			int code = Integer.parseInt(codeElement.getChildNodes().item(0).
					getNodeValue());
			Element messageElement = (Element)gamesDocument.getElementsByTagName(
					"message").item(0);
			String message = messageElement.getChildNodes().item(0).getNodeValue();
			
			throw new ServerException(code, message);
		}
		GameCTO gameCTO = new GameCTO(gameList, hasMore);
		return gameCTO;
	}

	public static boolean toBooleanOrExceptionRegister(HttpEntity entity) 
	throws Exception {

		Document gameDocument = parseHttpEntity(entity);
		
		if (gameDocument.getElementsByTagName("registered").getLength() == 1) {
		
			return true;
		}
		else {
			Element codeElement = (Element)gameDocument.getElementsByTagName(
					"code").item(0);
			int code = Integer.parseInt(codeElement.getChildNodes().item(0).
					getNodeValue());
			Element messageElement = (Element)gameDocument.getElementsByTagName(
					"message").item(0);
			String message = messageElement.getChildNodes().item(0).getNodeValue();
			
			throw new ServerException(code, message);
		}
	}
	
	public static boolean toBooleanOrExceptionUpdate(HttpEntity entity) 
	throws Exception {

		Document gameDocument = parseHttpEntity(entity);
		
		if (gameDocument.getElementsByTagName("updated").getLength() == 1) {
		
			return true;
		}
		else {
			Element codeElement = (Element)gameDocument.getElementsByTagName(
					"code").item(0);
			int code = Integer.parseInt(codeElement.getChildNodes().item(0).
					getNodeValue());
			Element messageElement = (Element)gameDocument.getElementsByTagName(
					"message").item(0);
			String message = messageElement.getChildNodes().item(0).getNodeValue();
			
			throw new ServerException(code, message);
		}
	}

	public static boolean toBooleanOrExceptionChangePassword(HttpEntity entity) 
	throws Exception {

		Document gameDocument = parseHttpEntity(entity);
		
		if (gameDocument.getElementsByTagName("passwordChanged").getLength() == 1) {
		
			return true;
		}
		else {
			Element codeElement = (Element)gameDocument.getElementsByTagName(
					"code").item(0);
			int code = Integer.parseInt(codeElement.getChildNodes().item(0).
					getNodeValue());
			Element messageElement = (Element)gameDocument.getElementsByTagName(
					"message").item(0);
			String message = messageElement.getChildNodes().item(0).getNodeValue();
			
			throw new ServerException(code, message);
		}
	}

	public static boolean toBooleanOrExceptionJoin(HttpEntity entity) 
	throws Exception {

		Document gameDocument = parseHttpEntity(entity);
		
		if (gameDocument.getElementsByTagName("joined").getLength() == 1) {
		
			return true;
		}
		else {
			Element codeElement = (Element)gameDocument.getElementsByTagName(
					"code").item(0);
			int code = Integer.parseInt(codeElement.getChildNodes().item(0).
					getNodeValue());
			Element messageElement = (Element)gameDocument.getElementsByTagName(
					"message").item(0);
			String message = messageElement.getChildNodes().item(0).getNodeValue();
			
			throw new ServerException(code, message);
		}
	}

	public static boolean toBooleanOrExceptionRemove(HttpEntity entity) 
	throws Exception {

		Document gameDocument = parseHttpEntity(entity);
		
		if (gameDocument.getElementsByTagName("abandoned").getLength() == 1) {
		
			return true;
		}
		else {
			Element codeElement = (Element)gameDocument.getElementsByTagName(
					"code").item(0);
			int code = Integer.parseInt(codeElement.getChildNodes().item(0).
					getNodeValue());
			Element messageElement = (Element)gameDocument.getElementsByTagName(
					"message").item(0);
			String message = messageElement.getChildNodes().item(0).getNodeValue();
			
			throw new ServerException(code, message);
		}
	}

	public static boolean toBooleanOrExceptionSend(HttpEntity entity) 
	throws Exception {

		Document gameDocument = parseHttpEntity(entity);
		
		if (gameDocument.getElementsByTagName("messageSent").getLength() == 1) {
		
			return true;
		}
		else {
			Element codeElement = (Element)gameDocument.getElementsByTagName(
					"code").item(0);
			int code = Integer.parseInt(codeElement.getChildNodes().item(0).
					getNodeValue());
			Element messageElement = (Element)gameDocument.getElementsByTagName(
					"message").item(0);
			String message = messageElement.getChildNodes().item(0).getNodeValue();
			
			throw new ServerException(code, message);
		}
	}
	
	private static InGamePlayerInfoTO 
	toInGamePlayerInfoTO(Element gameDocument) throws Exception {
		
		Element loginElement = (Element)gameDocument.getElementsByTagName(
		"login").item(0);
		String login = loginElement.getChildNodes().item(0).getNodeValue();
		
		Element pointsElement = (Element)gameDocument.getElementsByTagName(
				"points").item(0);
		int points = Integer.parseInt(
				pointsElement.getChildNodes().item(0).getNodeValue());
		Element itemsCaughtedElement = (Element)gameDocument.getElementsByTagName(
		"numberOfItems").item(0);
		int itemsCaughted = Integer.parseInt(
				itemsCaughtedElement.getChildNodes().item(0).getNodeValue());
		
		Element latitudeElement = (Element)gameDocument.getElementsByTagName(
		"latitude").item(0);
		int latitude = Integer.parseInt(
				latitudeElement.getChildNodes().item(0).getNodeValue());

		Element longitudeElement = (Element)gameDocument.getElementsByTagName(
		"longitude").item(0);
		int longitude = Integer.parseInt(
		longitudeElement.getChildNodes().item(0).getNodeValue());

		Element imageIdElement = (Element)gameDocument.getElementsByTagName(
		"imageId").item(0);
		int imageId= Integer.parseInt(
		imageIdElement.getChildNodes().item(0).getNodeValue());
		return new InGamePlayerInfoTO(login, points, itemsCaughted, 
				new GeoPoint(latitude, longitude),
				imageId);
	}
	
	private static Item 
	toItem(Element gameDocument) throws Exception {
		
		Element itemIdElement = (Element)gameDocument.getElementsByTagName(
		"itemId").item(0);
		long itemId = Long.parseLong(
				itemIdElement.getChildNodes().item(0).getNodeValue());
		
		Element typeElement = (Element)gameDocument.getElementsByTagName(
		"type").item(0);
		String type = typeElement.getChildNodes().item(0).getNodeValue();
		
		Element pointsElement = (Element)gameDocument.getElementsByTagName(
				"points").item(0);
		int points = Integer.parseInt(
				pointsElement.getChildNodes().item(0).getNodeValue());
		
		Element latitudeElement = (Element)gameDocument.getElementsByTagName(
		"latitude").item(0);
		int latitude = Integer.parseInt(
				latitudeElement.getChildNodes().item(0).getNodeValue());

		Element longitudeElement = (Element)gameDocument.getElementsByTagName(
		"longitude").item(0);
		int longitude = Integer.parseInt(
		longitudeElement.getChildNodes().item(0).getNodeValue());
		
		int typeInt = Item.COIN_TYPE;
		if (type.equals("QUE"))
			typeInt = Item.QUESTION_TYPE;
		else if (type.equals("BON"))
			typeInt = Item.BONUS_TYPE;
		return new Item(itemId, new GeoPoint(latitude, longitude), points, typeInt);
	}

	private static Message
	toMessage(Element gameDocument) throws Exception {

		String senderLogin = null;
		if (gameDocument.getElementsByTagName("senderLogin").getLength() == 1) {
			Element senderLoginElement = (Element)gameDocument.getElementsByTagName(
			"senderLogin").item(0);
			senderLogin = senderLoginElement.getChildNodes().item(0).getNodeValue();
		}
		
		Element bodyElement = (Element)gameDocument.getElementsByTagName(
		"body").item(0);
		String body = bodyElement.getChildNodes().item(0).getNodeValue();

		Element typeElement = (Element)gameDocument.getElementsByTagName(
		"type").item(0);
		int type = Integer.parseInt(typeElement.getChildNodes().item(0).getNodeValue());

		return new Message(senderLogin, null, body, type);
	}

	private static GenericGameResponseTO toGenericGameResponseTO(Element gameDocument) 
	throws Exception {
		GenericGameResponseTO genericGameResponseTO = new GenericGameResponseTO();
		
		if (gameDocument.getElementsByTagName("inGamePlayerInfos").getLength() == 1) {
			
			NodeList inGamePlayerInfos = 
				gameDocument.getElementsByTagName("inGamePlayerInfo");
			for (int i=0;i<inGamePlayerInfos.getLength();i++) {
				InGamePlayerInfoTO pl = toInGamePlayerInfoTO((Element)inGamePlayerInfos.item(i));
				genericGameResponseTO.getInGamePlayerInfoTOs().add(pl);
			}
		}

		if (gameDocument.getElementsByTagName("visibleItems").getLength() == 1) {
		
			NodeList visibleItems = 
				gameDocument.getElementsByTagName("visibleItem");
			for (int i=0;i<visibleItems.getLength();i++) {
				
				Item item = toItem((Element)visibleItems.item(i));
				genericGameResponseTO.getVisibleItems().add(item);
			}
		}
		
		if (gameDocument.getElementsByTagName("messages").getLength() == 1) {

			NodeList messages = 
				gameDocument.getElementsByTagName("message");
			for (int i=0;i<messages.getLength();i++) {

				Message message = toMessage((Element)messages.item(i));
				genericGameResponseTO.getMessages().add(message);
			}
		}

		if (gameDocument.getElementsByTagName("finished").getLength() == 1)		
			genericGameResponseTO.setHasFinished(true);

		return genericGameResponseTO;
	}
	
	public static StartOrContinueGameResponseTO toStartOrContinueGameResponseTO
	(HttpEntity entity) throws Exception {
		
		Document gameDocument = parseHttpEntity(entity);
		StartOrContinueGameResponseTO result = new StartOrContinueGameResponseTO();
		
		NodeList n = gameDocument.getElementsByTagName("startOrContinueGameReponse");
		
		if (n.getLength() == 1) {
			Element pointsElement = (Element)gameDocument.getElementsByTagName(
				"points").item(0);
			String points = pointsElement.getChildNodes().item(0).getNodeValue();
			result.setPoints(Integer.parseInt(points));
			Element numberOfItemsElement = (Element)gameDocument.getElementsByTagName(
				"numberOfItems").item(0);
			String numberOfItems = numberOfItemsElement.getChildNodes().item(0).getNodeValue();
			result.setNumberOfItems(Integer.parseInt(numberOfItems));
			if (gameDocument.getElementsByTagName("genericGameResponse").getLength() == 1)
				result.setGenericGameResponseTO(
						toGenericGameResponseTO(
								(Element)gameDocument.getElementsByTagName(
										"genericGameResponse").item(0)));
			return result;
		}
		else {
			Element codeElement = (Element)gameDocument.getElementsByTagName(
					"code").item(0);
			int code = Integer.parseInt(codeElement.getChildNodes().item(0).
					getNodeValue());
			Element messageElement = (Element)gameDocument.getElementsByTagName(
					"message").item(0);
			String message = messageElement.getChildNodes().item(0).getNodeValue();
			
			throw new ServerException(code, message);
		}
	}
	
	public static GenericGameResponseTO toGenericGameResponseTO(HttpEntity entity) 
	throws Exception {

		Document gameDocument = parseHttpEntity(entity);
		
		NodeList n = gameDocument.getElementsByTagName("genericGameResponse");
		
		if (n.getLength() == 1) {
			return toGenericGameResponseTO(
					(Element)gameDocument.getElementsByTagName("genericGameResponse").item(0));
		}
		else {
			Element codeElement = (Element)gameDocument.getElementsByTagName(
					"code").item(0);
			int code = Integer.parseInt(codeElement.getChildNodes().item(0).
					getNodeValue());
			Element messageElement = (Element)gameDocument.getElementsByTagName(
					"message").item(0);
			String message = messageElement.getChildNodes().item(0).getNodeValue();
			
			throw new ServerException(code, message);
		}
	}
	
	public static GetItemResponseTO toGetItemResponseTO(
			HttpEntity entity) throws Exception {
		
		Document gameDocument = parseHttpEntity(entity);
		GetItemResponseTO result = new GetItemResponseTO();
		
		NodeList n = gameDocument.getElementsByTagName("getItemResponse");
		
		if (n.getLength() == 1) {
			result.setGenericGameResponseTO(
				toGenericGameResponseTO(
						(Element)gameDocument.getElementsByTagName("genericGameResponse").item(0)));
			if (gameDocument.getElementsByTagName("actuallyGets").getLength() == 1)
				result.setActuallyTaken(gameDocument.getElementsByTagName("actuallyGets").getLength() == 1);
			else
				result.setActuallyTaken(false);
			if (result.isActuallyTaken()) {
				int playerPoints = Integer.parseInt(
						gameDocument.getElementsByTagName(
						"playerPoints").item(0).getChildNodes().item(0).getNodeValue());
				result.setPlayerPoints(playerPoints);
			}
			if (gameDocument.getElementsByTagName("question").getLength() == 1) {
				result.setQuestion(new Question());
				Element questionElement = (Element)gameDocument.getElementsByTagName(
				"questionText").item(0);
				String question = questionElement.getChildNodes().item(0).getNodeValue();
				result.getQuestion().setQuestion(question);
				if (gameDocument.getElementsByTagName("option1").getLength() == 1) {
					Element option1Element = (Element)gameDocument.getElementsByTagName(
					"option1").item(0);
					String option1 = option1Element.getChildNodes().item(0).getNodeValue();
					result.getQuestion().setOption1(option1);
				}
				if (gameDocument.getElementsByTagName("option2").getLength() == 1) {
					Element option2Element = (Element)gameDocument.getElementsByTagName(
					"option2").item(0);
					String option2 = option2Element.getChildNodes().item(0).getNodeValue();
					result.getQuestion().setOption2(option2);
				}
				if (gameDocument.getElementsByTagName("option3").getLength() == 1) {
					Element option3Element = (Element)gameDocument.getElementsByTagName(
					"option3").item(0);
					String option3 = option3Element.getChildNodes().item(0).getNodeValue();
					result.getQuestion().setOption3(option3);
				}
				Element answerElement = (Element)gameDocument.getElementsByTagName(
				"rightAnswer").item(0);
				int rightAnswer = Integer.parseInt(
						answerElement.getChildNodes().item(0).getNodeValue());
				result.getQuestion().setAnswer(rightAnswer);
			}
		}
		else {
			Element codeElement = (Element)gameDocument.getElementsByTagName(
					"code").item(0);
			int code = Integer.parseInt(codeElement.getChildNodes().item(0).
					getNodeValue());
			Element messageElement = (Element)gameDocument.getElementsByTagName(
					"message").item(0);
			String message = messageElement.getChildNodes().item(0).getNodeValue();
			
			throw new ServerException(code, message);
		}
		return result;
	}
	
	public static AnswerQuestionResponseTO toAnswerQuestionResponseTO(
			HttpEntity entity) throws Exception {
		
		Document gameDocument = parseHttpEntity(entity);
		AnswerQuestionResponseTO result = new AnswerQuestionResponseTO();
		
		NodeList n = gameDocument.getElementsByTagName("answerQuestionResponse");
		
		if (n.getLength() == 1) {
			result.setGenericGameResponseTO(
				toGenericGameResponseTO(
						(Element)gameDocument.getElementsByTagName("genericGameResponse").item(0)));

			Element numberOfBonudOpenedElement = (Element)gameDocument.getElementsByTagName(
				"numberOfBonusOpened").item(0);
			result.setNumberOfBonusOpened(Integer.parseInt(
					numberOfBonudOpenedElement.getChildNodes().item(0).getNodeValue()));
		}
		else {
			Element codeElement = (Element)gameDocument.getElementsByTagName(
					"code").item(0);
			int code = Integer.parseInt(codeElement.getChildNodes().item(0).
					getNodeValue());
			Element messageElement = (Element)gameDocument.getElementsByTagName(
					"message").item(0);
			String message = messageElement.getChildNodes().item(0).getNodeValue();
			
			throw new ServerException(code, message);
		}
		return result;
	}
}